/**
 * @file bsp.c
 * @author morris (a_morris@163.com)
 * @brief
 * @version 0.1
 * @date 2022-01-14
 *
 * @copyright Copyright (c) 2022
 *
 */
#include "bsp.h"

#include <stdint.h>
#include <time.h>

#include "lpm.h"
#include "lpuart.h"
#include "reset.h"
#include "wdt.h"
#include "bsp_control.h"

__WEAK void board_init(void) {}
__WEAK void board_low_power_init(void) {}

static volatile bsp_rtc_interrupt_callback_t s_bsp_rtc_interrupt_func = NULL;

static void sysctrl_init(void)
{
    stc_sysctrl_clk_cfg_t stcCfg;

    Sysctrl_SetRCHTrim(SysctrlRchFreq4MHz);

    Sysctrl_ClkSourceEnable(SysctrlClkXTL, TRUE);
    // Sysctrl_ClkSourceEnable(SysctrlClkRCL, TRUE);

    Sysctrl_SetPeripheralGate(SysctrlPeripheralTick, TRUE);
//    SysTick_Config(SystemCoreClock / 1000); // 1KHZ, systick timeout 1ms
}

static void sys_rtc_init(void)
{
    Sysctrl_SetPeripheralGate(SysctrlPeripheralRtc, TRUE);
    if (M0P_RTC->CR0_f.START == 0)
    {
        stc_rtc_initstruct_t RtcInitStruct;
        RtcInitStruct.rtcAmpm             = RtcPm;
        RtcInitStruct.rtcClksrc           = RtcClkXtl;
        RtcInitStruct.rtcPrdsel.rtcPrdsel = RtcPrdx;
        RtcInitStruct.rtcPrdsel.rtcPrdx   = 0;
        RtcInitStruct.rtcTime.u8Second    = 0x30;
        RtcInitStruct.rtcTime.u8Minute    = 0x02;
        RtcInitStruct.rtcTime.u8Hour      = 0x12;
        RtcInitStruct.rtcTime.u8Day       = 0x14;
        RtcInitStruct.rtcTime.u8DayOfWeek = 0x05;
        RtcInitStruct.rtcTime.u8Month     = 0x01;
        RtcInitStruct.rtcTime.u8Year      = 0x22;
        RtcInitStruct.rtcCompen           = RtcCompenEnable;
        RtcInitStruct.rtcCompValue        = 0;
        Rtc_Init(&RtcInitStruct);
    }
    Rtc_AlmIeCmd(TRUE);

    EnableNvic(RTC_IRQn, IrqLevel3, TRUE);
    Rtc_Cmd(TRUE);
    Rtc_StartWait();
}

void bsp_clock_init(void)
{
    sysctrl_init();
    bsp_wdt_init();
}

void bsp_init(void)
{
    led_init();

    sys_rtc_init();

    power_init();

    board_init();
}

//void bsp_delay_ms(uint32_t tick)
//{
//    volatile uint32_t _tick = tick * 0x1FF;
//    while (_tick--)
//        ;
//}
void bsp_delay_ms(uint32_t tick)
{
    /* all: 8 cycle, 最大误差: 1000 * 8 / 256 = 31.25us */
    volatile uint32_t _tick;
    __asm volatile("LSLS  %0, %1, #8                \n" : "=r"(_tick) : "r"(tick) : "memory"); /* 1 cycle */
    /* 要求:15.6 cycle, 实际: 16 cycle, 最小误差: 1 / 256 */
    __asm volatile("_delay_ms_loop_start:           \n" ::: "memory");
    __asm volatile("    NOP                         \n" ::: "memory");                          /* 1 cycle */
    __asm volatile("    NOP                         \n" ::: "memory");                          /* 1 cycle */
    __asm volatile("    NOP                         \n" ::: "memory");                          /* 1 cycle */
    __asm volatile("    NOP                         \n" ::: "memory");                          /* 1 cycle */
    __asm volatile("    CMP  %0, #0                 \n" ::"r"(_tick) : "memory");               /* 1 cycle */
    __asm volatile("    BEQ _DELAY_RET1             \n" ::: "memory");                          /* 1 or 3 cycle */
    __asm volatile("    SUBS %0, %0, #1             \n" : "=r"(_tick) : "r"(_tick) : "memory"); /* 1 cycle */
    __asm volatile("    B _delay_ms_loop_start      \n" ::: "memory");                          /* 3 cycle */
    __asm volatile("_DELAY_RET1:                    \n" ::: "memory");
}

void bsp_delay_us(uint32_t us)
{
    /* all: 8 cycle, 最大误差: 1000 * 8 / 256 = 31.25us */
    volatile uint32_t _tick;
    __asm volatile("LSRS   %0, %1, #2                \n" : "=r"(_tick) : "r"(us) : "memory"); /* 1 cycle */
    /* 要求:15.6 cycle, 实际: 16 cycle, 最小误差: 1 / 256 */
    __asm volatile("_delay_us_loop_start:           \n" ::: "memory");
    __asm volatile("    NOP                         \n" ::: "memory");                          /* 1 cycle */
    __asm volatile("    NOP                         \n" ::: "memory");                          /* 1 cycle */
    __asm volatile("    NOP                         \n" ::: "memory");                          /* 1 cycle */
    __asm volatile("    NOP                         \n" ::: "memory");                          /* 1 cycle */
    __asm volatile("    CMP  %0, #0                 \n" ::"r"(_tick) : "memory");               /* 1 cycle */
    __asm volatile("    BEQ _delay_us_return        \n" ::: "memory");                          /* 1 or 3 cycle */
    __asm volatile("    SUBS %0, %0, #1             \n" : "=r"(_tick) : "r"(_tick) : "memory"); /* 1 cycle */
    __asm volatile("    B _delay_us_loop_start      \n" ::: "memory");                          /* 3 cycle */
    __asm volatile("_delay_us_return:               \n" ::: "memory");
}
void bsp_rtc_interrupt_register(bsp_rtc_interrupt_callback_t callback)
{
    s_bsp_rtc_interrupt_func = callback;
}

uint32_t bsp_get_datetime(bsp_time_t* time)
{
    struct tm      info;
    stc_rtc_time_t readtime;
    Rtc_ReadDateTime(&readtime);

    info.tm_year = (((readtime.u8Year >> 4) * 10) + (readtime.u8Year & 0x0f))
                 + (2000 - 1900);
    info.tm_mon
        = (((readtime.u8Month >> 4) * 10) + (readtime.u8Month & 0x0f)) - 1;
    info.tm_mday = (((readtime.u8Day >> 4) * 10) + (readtime.u8Day & 0x0f));
    info.tm_hour = (((readtime.u8Hour >> 4) * 10) + (readtime.u8Hour & 0x0f));
    info.tm_min
        = (((readtime.u8Minute >> 4) * 10) + (readtime.u8Minute & 0x0f));
    info.tm_sec
        = (((readtime.u8Second >> 4) * 10) + (readtime.u8Second & 0x0f));

    if (time)
    {
        time->year   = info.tm_year + 1900;
        time->month  = info.tm_mon + 1;
        time->day    = info.tm_mday;
        time->week   = readtime.u8DayOfWeek & 0x0f;
        time->hour   = info.tm_hour;
        time->minute = info.tm_min;
        time->second = info.tm_sec;
    }

    return mktime(&info);
}

void bsp_low_power_init(void)
{
    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);
#ifdef NDEBUG
    // swd as gpio
   // Sysctrl_SetFunc(SysctrlSWDUseIOEn, TRUE);
#endif

	
  M0P_GPIO->PAADS = 0;
  M0P_GPIO->PBADS = 0;
  M0P_GPIO->PCADS = 0;
  M0P_GPIO->PDADS = 0;

  M0P_GPIO->PCADS |= 0xC010;  // 32768晶振IO配置为模拟IO

  board_low_power_init();
	
	/*todo 20241211*/
	bsp_Power_Low_Init();
	
}

void bsp_deep_sleep(void)
{
#ifdef NDEBUG
    Sysctrl_SetFunc(SysctrlSWDUseIOEn, TRUE);
    Lpm_GotoDeepSleep(FALSE);
#else
    SCB->SCR = 0;
    __WFI();
#endif
#ifdef NDEBUG
    Sysctrl_SetFunc(SysctrlSWDUseIOEn, FALSE);
#endif
}

void bsp_wdt_init(void)
{
#ifdef WDT_EN
    Sysctrl_SetPeripheralGate(SysctrlPeripheralWdt, TRUE);

    Wdt_Init(WdtResetEn, WdtT6s55);
#endif
}

void bsp_wdt_feed(void)
{
#ifdef WDT_EN
    Wdt_Feed();
#endif
}

void bsp_reboot(void) { NVIC_SystemReset(); }

uint8_t bsp_get_reset_flag(void)
{
    uint8_t reset = (uint8_t) (M0P_RESET->RESET_FLAG & 0xff);
    Reset_ClearFlagAll();
    return reset;
}

#define DEVICE_SN_ADDRESS (0x0000FE0C)
uint8_t bps_get_device_type(void)
{
#if (DEVICE_TYPE == 0x00)
    const bk9000_sn_t *const data = ((const bk9000_sn_t *const) DEVICE_SN_ADDRESS);
    return data->id[5];
#else
    return (uint8_t) (DEVICE_TYPE & 0xff);
#endif
}


void bsp_log_init(void)
{
    SEGGER_RTT_Init();
    SEGGER_RTT_SetTerminal(0);
}

int bsp_log_vprintf(const char *format, va_list _va_list)
{
#define BUFFER_INDEX 0
    return SEGGER_RTT_vprintf(BUFFER_INDEX, format, &_va_list);
}


void bps_get_loat_number(const bk9000_sn_t** const sn)
{
    const bk9000_sn_t *const data = ((const bk9000_sn_t *const) DEVICE_SN_ADDRESS);
    *sn                           = data;
    if (data->id[5] == 0xff)
    {
        uint8_t *tmp_sn = (uint8_t *) data;
        tmp_sn[5]       = bps_get_device_type();
    }
}
void Rtc_IRQHandler(void)
{
    if (Rtc_GetPridItStatus() == TRUE)
    {
        Rtc_ClearPrdfItStatus(); //清除中断标志位

        if (s_bsp_rtc_interrupt_func) s_bsp_rtc_interrupt_func();
    }
}
/*old  rtc do*/
//void Rtc_IRQHandler(void)
//{
//    if (Rtc_GetPridItStatus() == TRUE)
//    {
//		static volatile uint8_t twoday_count=0;
//        Rtc_ClearPrdfItStatus(); //清除中断标志位
//        bsp_wdt_feed();          // rtc中断中喂狗
//		static uint8_t run_count=0;
//		static uint8_t temp_count=0;
//		
//		/*采集启动标志位*/
//		if(!temp_flag.start)
//		{
//			temp_count++;
//			if(temp_count==2)
//			{
//				temp_flag.start=1;
//				temp_count=0;
//			}
//		}
//		if(!ntc.flag)
//		{
//			ntc.count++;
//			if(ntc.count==25)
//			{
//				ntc.flag=1;
//				ntc.count=0;
//			}
//		}
//		
//		/*低温升温模式恢复计时8分钟*/
//		if(temp_flag.low_start)
//		{
//			if(temp_low_reset_count<960)
//			{
//				temp_low_reset_count++;
//			}
//			
//			if(temp_low_reset_count==960)
//			{
//				temp_flag.low_reset_start=1;//低温恢复检测标志位
//			}
//		}
//		else
//		{
//			if(temp_low_reset_count)
//				temp_low_reset_count=0;
//		}
//        if (s_bsp_rtc_interrupt_func) s_bsp_rtc_interrupt_func();
//    }
//}
